﻿namespace Sidvall.CodeGenerator.Collections
{
	public static class EnumerableExtension
	{
		#region Add

		public static void Add(this System.Collections.IEnumerable items, object item)
		{
			var list1 = items as System.Collections.IList;
			if (list1 != null)
				list1.Add(item);
		}

		#endregion
		#region Any

		public static bool Any(this System.Collections.IEnumerable items)
		{
			System.Collections.ICollection collection;
			System.Collections.IEnumerator enumerator;
			bool result;

			if (items == null)
				return false;
			collection = items as System.Collections.ICollection;
			if (collection != null)
				return collection.Count > 0;
			enumerator = items.GetEnumerator();
			result = enumerator.MoveNext();
			enumerator.Reset();

			return result;
		}

		#endregion
		#region CastToEnumArray

		public static T[] CastToEnumArray<T>(this System.Collections.IEnumerable items)
		{
			System.Collections.Generic.List<T> list;

			if (items == null)
				return null;
			list = new System.Collections.Generic.List<T>();
			foreach (var item in items)
			{
				if (item is T)
					list.Add((T)item);
				else
					list.Add((T)System.Enum.ToObject(typeof(T), item));
			}

			return list.ToArray();
		}

		#endregion
		#region Clear

		public static void Clear(this System.Collections.IEnumerable items)
		{
			var list1 = items as System.Collections.IList;
			if (list1 != null)
				list1.Clear();
		}

		#endregion
		#region FirstOrDefault

		public static object FirstOrDefault(this System.Collections.IEnumerable items)
		{
			System.Collections.IList collection;
			System.Collections.IEnumerator enumerator;
			object result;

			if (items == null)
				return null;
			collection = items as System.Collections.IList;
			if (collection != null)
			{
				if (collection.Count > 0)
					return collection[0];
				return null;
			}
			enumerator = items.GetEnumerator();
			if (enumerator.MoveNext())
				result = enumerator.Current;
			else
				result = null;
			enumerator.Reset();

			return result;
		}

		#endregion
		#region IsNullOrEmpty

		public static bool IsNullOrEmpty(this System.Collections.IEnumerable items)
		{
			if (items == null)
				return true;
			if (!items.Any())
				return true;
			return false;
		}

		#endregion
		#region JoinToString

		public static string JoinToString(this System.Collections.IEnumerable items, char separator)
		{
			return JoinToString(items, separator.ToString());
		}
		public static string JoinToString(this System.Collections.IEnumerable items, string separator)
		{
			return JoinToString(items, separator, false);
		}
		public static string JoinToString(this System.Collections.Generic.IEnumerable<double> items, char separator)
		{
			return JoinToString(items, separator.ToString());
		}
		public static string JoinToString(this System.Collections.Generic.IEnumerable<double> items, string separator)
		{
			return JoinToString(items, separator, false, o =>
			{
				return o.ToString(System.Globalization.CultureInfo.InvariantCulture);
			});
		}
		public static string JoinToString(this System.Collections.IEnumerable items, string separator, bool removeEmptyEntries)
		{
			return JoinToString(items, separator, removeEmptyEntries, o =>
			{
				if (o != null)
					return o.ToString();
				else
					return string.Empty;
			});
		}
		private static string JoinToString(System.Collections.IEnumerable items, string separator, bool removeEmptyEntries, System.Func<object, string> converter)
		{
			System.Text.StringBuilder sb;
			string value;
			bool firstRow;

			firstRow = true;
			sb = new System.Text.StringBuilder();
			if (items != null)
			{
				foreach (var item in items)
				{
					value = converter(item);
					if ((removeEmptyEntries) && (string.IsNullOrWhiteSpace(value)))
						continue;
					if ((!firstRow) && (separator != null))
						sb.Append(separator);
					sb.Append(value);
					firstRow = false;
				}
			}

			return sb.ToString();
		}
		private static string JoinToString<T>(System.Collections.Generic.IEnumerable<T> items, string separator, bool removeEmptyEntries, System.Func<T, string> converter)
		{
			System.Text.StringBuilder sb;
			string value;
			bool firstRow;

			firstRow = true;
			sb = new System.Text.StringBuilder();
			if (items != null)
			{
				foreach (var item in items)
				{
					value = converter(item);
					if ((removeEmptyEntries) && (string.IsNullOrWhiteSpace(value)))
						continue;
					if ((!firstRow) && (separator != null))
						sb.Append(separator);
					sb.Append(value);
					firstRow = false;
				}
			}

			return sb.ToString();
		}

		#endregion
		#region Remove

		public static void Remove(this System.Collections.IEnumerable items, object item)
		{
			var list1 = items as System.Collections.IList;
			if (list1 != null)
				list1.Remove(item);
		}

		#endregion
		#region ToDictionary

		public static System.Collections.Generic.Dictionary<TKey, TItem> ToDictionary<TKey, TItem>(this System.Collections.Generic.IEnumerable<TItem> items, System.Func<TItem, TKey> getKeyHandler, bool removeDuplicates)
		{
			System.Collections.Generic.Dictionary<TKey, TItem> list;
			TKey value;

			if (getKeyHandler == null)
				throw new System.ArgumentNullException("getKeyHandler");
			if (items == null)
				return null;

			list = new System.Collections.Generic.Dictionary<TKey, TItem>();
			foreach (var item in items)
			{
				value = getKeyHandler(item);
				if (value != null)
				{
					if ((!removeDuplicates) || (!list.ContainsKey(value)))
						list.Add(value, item);
				}
			}

			return list;
		}

		#endregion
		#region ToDictionaryCollection

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
		public static System.Collections.Generic.Dictionary<TKey, System.Collections.ObjectModel.Collection<TItem>> ToDictionaryCollection<TKey, TItem>(this System.Collections.Generic.IEnumerable<TItem> items, System.Func<TItem, TKey> getKeyHandler)
		{
			System.Collections.Generic.Dictionary<TKey, System.Collections.ObjectModel.Collection<TItem>> index;
			System.Collections.ObjectModel.Collection<TItem> list;
			TKey value;

			if (getKeyHandler == null)
				throw new System.ArgumentNullException("getKeyHandler");
			if (items == null)
				return null;
			index = new System.Collections.Generic.Dictionary<TKey, System.Collections.ObjectModel.Collection<TItem>>();
			foreach (var item in items)
			{
				value = getKeyHandler(item);
				if (value != null)
				{
					if (!index.TryGetValue(value, out list))
					{
						list = new System.Collections.ObjectModel.Collection<TItem>();
						index.Add(value, list);
					}
					list.Add(item);
				}
			}

			return index;
		}

		#endregion
		#region ToSortedDictionary

		public static System.Collections.Generic.SortedDictionary<TKey, TItem> ToSortedDictionary<TKey, TItem>(this System.Collections.Generic.IEnumerable<TItem> items, System.Func<TItem, TKey> getKeyHandler, bool removeDuplicates)
		{
			System.Collections.Generic.SortedDictionary<TKey, TItem> list;
			TKey value;

			if (getKeyHandler == null)
				throw new System.ArgumentNullException("getKeyHandler");
			if (items == null)
				return null;

			list = new System.Collections.Generic.SortedDictionary<TKey, TItem>();
			foreach (var item in items)
			{
				value = getKeyHandler(item);
				if (value != null)
				{
					if ((!removeDuplicates) || (!list.ContainsKey(value)))
						list.Add(value, item);
				}
			}

			return list;
		}

		#endregion
		#region ToSortedDictionaryCollection

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
		public static System.Collections.Generic.SortedDictionary<TKey, System.Collections.ObjectModel.Collection<TItem>> ToSortedDictionaryCollection<TKey, TItem>(this System.Collections.Generic.IEnumerable<TItem> items, System.Func<TItem, TKey> getKeyHandler)
		{
			System.Collections.Generic.SortedDictionary<TKey, System.Collections.ObjectModel.Collection<TItem>> index;
			System.Collections.ObjectModel.Collection<TItem> list;
			TKey value;

			if (getKeyHandler == null)
				throw new System.ArgumentNullException("getKeyHandler");
			if (items == null)
				return null;
			index = new System.Collections.Generic.SortedDictionary<TKey, System.Collections.ObjectModel.Collection<TItem>>();
			foreach (var item in items)
			{
				value = getKeyHandler(item);
				if (value != null)
				{
					if (!index.TryGetValue(value, out list))
					{
						list = new System.Collections.ObjectModel.Collection<TItem>();
						index.Add(value, list);
					}
					list.Add(item);
				}
			}

			return index;
		}

		#endregion
		#region ToEnumArray

		public static T[] ToEnumArray<T>(this System.Collections.Generic.IEnumerable<string> items)
		{
			System.Collections.Generic.List<T> list;
			T value;

			if (items == null)
				return null;

			list = new System.Collections.Generic.List<T>();
			foreach (var item in items)
			{
				value = (T)System.Enum.Parse(typeof(T), item, true);
				list.Add(value);
			}

			return list.ToArray();
		}

		#endregion
		#region ToHashSet

		public static System.Collections.Generic.HashSet<TKey> ToHashSet<TKey, TItem>(this System.Collections.Generic.IEnumerable<TItem> items, System.Func<TItem, TKey> getKeyHandler, bool removeDuplicates)
		{
			System.Collections.Generic.HashSet<TKey> list;
			TKey value;

			if (getKeyHandler == null)
				throw new System.ArgumentNullException("getKeyHandler");
			if (items == null)
				return null;

			list = new System.Collections.Generic.HashSet<TKey>();
			foreach (var item in items)
			{
				value = getKeyHandler(item);
				if (value != null)
				{
					if ((!removeDuplicates) || (!list.Contains(value)))
						list.Add(value);
				}
			}

			return list;
		}

		#endregion
		#region ToDoubleArray

		public static double[] ToDoubleArray(this System.Collections.Generic.IEnumerable<string> items)
		{
			System.Collections.Generic.List<double> list;
			double value;

			if (items == null)
				return null;

			list = new System.Collections.Generic.List<double>();
			foreach (var item in items)
			{
				if (double.TryParse(item, out value))
					list.Add(value);
			}

			return list.ToArray();
		}
		public static double[] ToDoubleArray(this System.Collections.Generic.IEnumerable<string> items, System.Globalization.NumberStyles style, System.IFormatProvider provider)
		{
			System.Collections.Generic.List<double> list;
			double value;

			if (items == null)
				return null;

			list = new System.Collections.Generic.List<double>();
			foreach (var item in items)
			{
				if (double.TryParse(item, style, provider, out value))
					list.Add(value);
			}

			return list.ToArray();
		}

		#endregion
		#region ToInt32Array

		public static int[] ToInt32Array(this System.Collections.Generic.IEnumerable<string> items)
		{
			System.Collections.Generic.List<int> list;
			int value;

			if (items == null)
				return null;

			list = new System.Collections.Generic.List<int>();
			foreach (var item in items)
			{
				if (int.TryParse(item, out value))
					list.Add(value);
			}

			return list.ToArray();
		}
		public static int[] ToInt32Array(this System.Collections.Generic.IEnumerable<string> items, System.Globalization.NumberStyles style, System.IFormatProvider provider)
		{
			System.Collections.Generic.List<int> list;
			int value;

			if (items == null)
				return null;

			list = new System.Collections.Generic.List<int>();
			foreach (var item in items)
			{
				if (int.TryParse(item, style, provider, out value))
					list.Add(value);
			}

			return list.ToArray();
		}

		#endregion
		#region ToInt64Array

		public static long[] ToInt64Array(this System.Collections.Generic.IEnumerable<string> items)
		{
			System.Collections.Generic.List<long> list;
			long value;

			if (items == null)
				return null;

			list = new System.Collections.Generic.List<long>();
			foreach (var item in items)
			{
				if (long.TryParse(item, out value))
					list.Add(value);
			}

			return list.ToArray();
		}
		public static long[] ToInt64Array(this System.Collections.Generic.IEnumerable<string> items, System.Globalization.NumberStyles style, System.IFormatProvider provider)
		{
			System.Collections.Generic.List<long> list;
			long value;

			if (items == null)
				return null;

			list = new System.Collections.Generic.List<long>();
			foreach (var item in items)
			{
				if (long.TryParse(item, style, provider, out value))
					list.Add(value);
			}

			return list.ToArray();
		}

		#endregion
		#region ToStringArray

		public static string[] ToStringArray(this System.Collections.Generic.IEnumerable<int> items)
		{
			System.Collections.Generic.List<string> list;

			if (items == null)
				return null;

			list = new System.Collections.Generic.List<string>();
			foreach (var item in items)
				list.Add(item.ToString(System.Globalization.CultureInfo.InvariantCulture));

			return list.ToArray();
		}
		public static string[] ToStringArray(this System.Collections.Generic.IEnumerable<long> items)
		{
			System.Collections.Generic.List<string> list;

			if (items == null)
				return null;

			list = new System.Collections.Generic.List<string>();
			foreach (var item in items)
				list.Add(item.ToString(System.Globalization.CultureInfo.InvariantCulture));

			return list.ToArray();
		}

		#endregion
	}
}
